home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / macos / uae069b2.src.cpt.hqx / UAE069ß2.SRC.CPT / uae069fl2.src / autoconf.c < prev    next >
C/C++ Source or Header  |  1997-06-13  |  11KB  |  485 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * AutoConfig devices
  5.   *
  6.   * Copyright 1995, 1996 Bernd Schmidt
  7.   * Copyright 1996 Ed Hanway
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12.  
  13. #include "config.h"
  14. #include "options.h"
  15. #include "machdep/m68k.h"
  16. #include "uae.h"
  17. #include "my_memory.h"
  18. #include "custom.h"
  19. #include "readcpu.h"
  20. #include "newcpu.h"
  21. #include "disk.h"
  22. #include "xwin.h"
  23. #include "autoconf.h"
  24. #include "osdep/exectasks.h"
  25. #include "threaddep/penguin.h"
  26.  
  27. /* We'll need a lot of these. */
  28. #define MAX_TRAPS 4096
  29. static TrapFunction traps[MAX_TRAPS];
  30. static int trapmode[MAX_TRAPS];
  31. static const char *trapstr[MAX_TRAPS];
  32. static uaecptr trapoldfunc[MAX_TRAPS];
  33.  
  34. static int max_trap = 0;
  35. int lasttrap;
  36.  
  37. /* Stack management */
  38.  
  39. /* The mechanism for doing m68k calls from native code is as follows:
  40.  * 
  41.  * m68k code executes, stack is main
  42.  * calltrap to execute_fn_on_extra_stack. new stack is allocated
  43.  * do_stack_magic is called for the first time
  44.  * current context is saved with setjmp [0]
  45.  *  transfer_control is done
  46.  *   native code executes on new stack
  47.  *   native code calls call_m68k
  48.  *   setjmp saves current context [1]
  49.  *  longjmp back to execute_fn_on_extra_stack [0]
  50.  * pointer to new stack is saved on m68k stack. m68k return address set
  51.  * to 0xF0FF00. m68k PC set to called function
  52.  * m68k function executes, stack is main
  53.  * m68k function returns to 0xF0FF00
  54.  * calltrap to m68k_mode_return
  55.  * do_stack_magic is called again
  56.  * current context is saved again with setjmp [0]
  57.  *  this time, transfer_control is _not_ done, instead a longjmp[1]
  58.  *  to the previously saved context
  59.  *   native code executes again on temp stack
  60.  *   native function returns to stack_stub
  61.  *  longjmp[0] back to old context
  62.  * back again!
  63.  * 
  64.  * A bearded man enters the room, carrying a bowl of spaghetti.
  65.  */
  66.  
  67. /* This _shouldn't_ crash with a stack size of 4096, but it does...
  68.  * might be a bug */
  69. #ifndef EXTRA_STACK_SIZE
  70. #define EXTRA_STACK_SIZE 65536
  71. #endif
  72.  
  73. static void *extra_stack_list = NULL;
  74.  
  75. static void *get_extra_stack(void)
  76. {
  77.     void *s = extra_stack_list;
  78.     if (s)
  79.     extra_stack_list = *(void **)s;
  80.     if (!s)
  81.     s = malloc (EXTRA_STACK_SIZE);
  82.     return s;
  83. }
  84.  
  85. static void free_extra_stack (void *s)
  86. {
  87.     *(void **)s = extra_stack_list;
  88.     extra_stack_list = s;
  89. }
  90.  
  91. static void stack_stub (void *s, TrapFunction f, uae_u32 *retval)
  92. {
  93. #ifdef CAN_DO_STACK_MAGIC
  94.     /*printf("in stack_stub: %p %p %p %x\n", s, f, retval, (int)*retval);*/
  95.     *retval = f();
  96.     /*write_log ("returning from stack_stub\n");*/
  97.     longjmp(((jmp_buf *)s)[0], 1);
  98. #endif
  99. }
  100.  
  101. static void *current_extra_stack = NULL;
  102. static uaecptr m68k_calladdr;
  103.  
  104. static void do_stack_magic(TrapFunction f, void *s, int has_retval)
  105. {
  106. #ifdef CAN_DO_STACK_MAGIC
  107.     uaecptr a7;
  108.     jmp_buf *j = (jmp_buf *)s;
  109.     switch (setjmp(j[0])) {
  110.      case 0:
  111.     /* Returning directly */
  112.     current_extra_stack = s;
  113.     if (has_retval == -1) {
  114.         /*write_log ("finishing m68k mode return\n");*/
  115.         longjmp(j[1], 1);
  116.     }
  117.     /*write_log ("calling native function\n");*/
  118.     transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval);
  119.     /* not reached */
  120.     abort();
  121.  
  122.      case 1:
  123.     /*write_log ("native function complete\n");*/
  124.     /* Returning normally. */
  125.     if (stack_has_retval(s, EXTRA_STACK_SIZE))
  126.         m68k_dreg(regs, 0) = get_retval_from_stack(s, EXTRA_STACK_SIZE);
  127.     free_extra_stack(s);
  128.     break;
  129.  
  130.      case 2:
  131.     /* Returning to do a m68k call. We're now back on the main stack. */
  132.     a7 = m68k_areg(regs, 7) -= (sizeof (void *) + 7) & ~3;
  133.     /* Save stack to restore */
  134.     *((void **)get_real_address(a7 + 4)) = s;
  135.     /* Save special return address: this address contains a
  136.      * calltrap that will longjmp to the right stack. */
  137.     put_long (m68k_areg(regs, 7), 0xF0FF00);
  138.     m68k_setpc(m68k_calladdr);
  139.     /*write_log ("native function calls m68k\n");*/
  140.     break;
  141.     }
  142.     current_extra_stack = 0;
  143. #endif
  144. }
  145.  
  146. static uae_u32 execute_fn_on_extra_stack(TrapFunction f, int has_retval)
  147. {
  148.     uae_u32 retval = 0;
  149. #ifdef CAN_DO_STACK_MAGIC
  150.     void *s = get_extra_stack();
  151.     do_stack_magic (f, s, has_retval);
  152. #endif
  153.     return 0;
  154. }
  155.  
  156. static uae_u32 m68k_mode_return(void)
  157. {
  158. #ifdef CAN_DO_STACK_MAGIC
  159.     uaecptr a7 = m68k_areg(regs, 7);
  160.     void *s = *(void **)get_real_address(a7);
  161.     m68k_areg(regs, 7) += (sizeof (void *) + 3) & ~3;
  162.     /*write_log ("doing m68k mode return\n");*/
  163.     do_stack_magic (NULL, s, -1);
  164. #endif
  165.     return 0;
  166. }
  167.  
  168. static uae_u32 call_m68k(uaecptr addr, int saveregs)
  169. {
  170.     uae_u32 retval = 0;
  171.     volatile int do_save = saveregs;
  172.     if (current_extra_stack == NULL)
  173.     abort();
  174. #ifdef CAN_DO_STACK_MAGIC
  175.     {
  176.     volatile struct regstruct saved_regs;
  177.     jmp_buf *j = (jmp_buf *)current_extra_stack;
  178.     
  179.     if (do_save)
  180.         saved_regs = regs;
  181.     m68k_calladdr = addr;
  182.     switch (setjmp(j[1])) {
  183.      case 0:
  184.         /*write_log ("doing call\n");*/
  185.         /* Returning directly: now switch to main stack and do the call */
  186.         longjmp (j[0], 2);
  187.      case 1:
  188.         /*write_log ("returning from call\n");*/
  189.         retval = m68k_dreg (regs, 0);
  190.         if (do_save)
  191.         regs = saved_regs;
  192.         /* Returning after the call. */
  193.         break;
  194.     }
  195.     }
  196. #endif
  197.     return retval;
  198. }
  199.  
  200. uae_u32 CallLib(uaecptr base, uae_s16 offset)
  201. {
  202.     int i;
  203.     uaecptr olda6 = m68k_areg(regs, 6);
  204.     uae_u32 retval;
  205. #if 0
  206.     for (i = 0; i < n_libpatches; i++) {
  207.     if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
  208.         return (*libpatches[i].functions[-offset/6])();
  209.     }
  210. #endif
  211.     m68k_areg(regs, 6) = base;
  212.     retval = call_m68k(base + offset, 1);
  213.     m68k_areg(regs, 6) = olda6;
  214.     return retval;
  215. }
  216.  
  217. /* Commonly used autoconfig strings */
  218.  
  219. uaecptr EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion;
  220. uaecptr EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36;
  221. uaecptr EXPANSION_bootcode, EXPANSION_nullfunc;
  222.  
  223. static int current_deviceno = 0;
  224.  
  225. int get_new_device(char **devname, uaecptr *devname_amiga)
  226. {
  227.     char buffer[80];
  228.     
  229.     sprintf(buffer,"UAE%d", current_deviceno);
  230.  
  231.     *devname_amiga = ds(*devname = my_strdup(buffer));
  232.     return current_deviceno++;
  233. }
  234.  
  235. /* ROM tag area memory access */
  236.  
  237. static uae_u8 rtarea[65536];
  238.  
  239. static uae_u32 rtarea_lget(uaecptr) REGPARAM;
  240. static uae_u32 rtarea_wget(uaecptr) REGPARAM;
  241. static uae_u32 rtarea_bget(uaecptr) REGPARAM;
  242. static void  rtarea_lput(uaecptr, uae_u32) REGPARAM;
  243. static void  rtarea_wput(uaecptr, uae_u32) REGPARAM;
  244. static void  rtarea_bput(uaecptr, uae_u32) REGPARAM;
  245. static uae_u8 *rtarea_xlate(uaecptr) REGPARAM;
  246.  
  247. addrbank rtarea_bank = {
  248.     rtarea_lget, rtarea_wget, rtarea_bget,
  249.     rtarea_lput, rtarea_wput, rtarea_bput,
  250.     rtarea_xlate, default_check
  251. };
  252.  
  253. uae_u8 REGPARAM2 *rtarea_xlate(uaecptr addr) 
  254. {
  255.     addr &= 0xFFFF;
  256.     return rtarea + addr;
  257. }
  258.  
  259. uae_u32 REGPARAM2 rtarea_lget(uaecptr addr)
  260. {
  261.     addr &= 0xFFFF;
  262.     return (uae_u32)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2);
  263. }
  264.  
  265. uae_u32 REGPARAM2 rtarea_wget(uaecptr addr)
  266. {
  267.     addr &= 0xFFFF;
  268.     return (rtarea[addr]<<8) + rtarea[addr+1];
  269. }
  270.  
  271. uae_u32 REGPARAM2 rtarea_bget(uaecptr addr)
  272. {
  273.     uae_u16 data;
  274.     addr &= 0xFFFF;
  275.     return rtarea[addr];
  276. }
  277.  
  278. void REGPARAM2 rtarea_lput(uaecptr addr, uae_u32 value) { }
  279. void REGPARAM2 rtarea_bput(uaecptr addr, uae_u32 value) { }
  280.  
  281. /* Don't start at 0 -- can get bogus writes there. */
  282. static uae_u32 trap_base_addr = 0x00F00180;
  283.  
  284. static int trace_traps = 1;
  285.  
  286. void REGPARAM2 rtarea_wput(uaecptr addr, uae_u32 value)
  287. {
  288.     uae_u32 retval = 0;
  289.     uae_u32 func = ((addr  - trap_base_addr) & 0xFFFF) >> 1;
  290.     int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0;
  291.     
  292.     if (*trapstr[func] != 0 && trace_traps) {
  293.     sprintf (warning_buffer, "TRAP: %s\n", trapstr[func]);
  294.     write_log (warning_buffer);
  295.     }
  296.  
  297.     /* For monitoring only? */
  298.     if (traps[func] == NULL) {
  299.     m68k_setpc(trapoldfunc[func]);
  300.     return;
  301.     }
  302.  
  303.     if (func < max_trap) {
  304.     if (trapmode[func] & TRAPFLAG_EXTRA_STACK) {
  305.         execute_fn_on_extra_stack(traps[func], has_retval);
  306.         return;
  307.     }
  308.     retval = (*traps[func])();
  309.     } else {
  310.     fprintf(stderr, "illegal emulator trap\n");
  311.     }
  312.     if (has_retval)
  313.     m68k_dreg(regs, 0) = retval;
  314. }
  315.  
  316. /* @$%&§ compiler bugs */
  317. static volatile int four = 4;
  318.     
  319. uaecptr libemu_InstallFunctionFlags(TrapFunction f, uaecptr libbase, int offset,
  320.                     int flags, const char *tracename)
  321. {
  322.     int i;
  323.     uaecptr retval;
  324.     uaecptr execbase = get_long(four);
  325.     int trnum;
  326.     uaecptr addr = here();
  327.     calltrap(trnum = deftrap2(f, flags, tracename));
  328.     dw(RTS);
  329.  
  330.     m68k_areg(regs, 1) = libbase;
  331.     m68k_areg(regs, 0) = offset;
  332.     m68k_dreg(regs, 0) = addr;
  333.     retval = CallLib(execbase, -420);
  334.  
  335.     trapoldfunc[trnum] = retval;
  336. #if 0
  337.     for (i = 0; i < n_libpatches; i++) {
  338.     if (libpatches[i].libbase == libbase)
  339.         break;
  340.     }
  341.     if (i == n_libpatches) {
  342.     int j;
  343.     libpatches[i].libbase = libbase;
  344.     for (j = 0; j < 300; j++)
  345.         libpatches[i].functions[j] = NULL;
  346.     n_libpatches++;
  347.     }
  348.     libpatches[i].functions[-offset/6] = f;
  349. #endif
  350.     return retval;
  351. }
  352.  
  353. /* some quick & dirty code to fill in the rt area and save me a lot of
  354.  * scratch paper
  355.  */
  356.  
  357. static int rt_addr = 0;
  358. static int rt_straddr = 0xFF00 - 2;
  359.  
  360. uae_u32 addr(int ptr)
  361. {
  362.     return (uae_u32)ptr + 0x00F00000;
  363. }
  364.  
  365. void db(uae_u8 data)
  366. {
  367.     rtarea[rt_addr++] = data;
  368. }
  369.  
  370. void dw(uae_u16 data)
  371. {
  372.     rtarea[rt_addr++] = data >> 8;
  373.     rtarea[rt_addr++] = data;
  374. }
  375.  
  376. void dl(uae_u32 data)
  377. {
  378.     rtarea[rt_addr++] = data >> 24;
  379.     rtarea[rt_addr++] = data >> 16;
  380.     rtarea[rt_addr++] = data >> 8;
  381.     rtarea[rt_addr++] = data;
  382. }
  383.  
  384. /* store strings starting at the end of the rt area and working
  385.  * backward.  store pointer at current address
  386.  */
  387.  
  388. uae_u32 ds(char *str)
  389. {
  390.     int len = strlen(str) + 1;
  391.  
  392.     rt_straddr -= len;
  393.     strcpy((char *)rtarea + rt_straddr, str);
  394.     
  395.     return addr(rt_straddr);
  396. }
  397.  
  398. void calltrap(uae_u32 n)
  399. {
  400.     dw(0x33C0);    /* MOVE.W D0,abs32 */
  401.     dl(n*2 + trap_base_addr);
  402. }
  403.  
  404. void org(uae_u32 a)
  405. {
  406.     rt_addr = a - 0x00F00000;
  407. }
  408.  
  409. uae_u32 here(void)
  410. {
  411.     return addr(rt_addr);
  412. }
  413.  
  414. int deftrap2(TrapFunction func, int mode, const char *str)
  415. {
  416.     int num = max_trap++;
  417.     traps[num] = func;
  418.     trapstr[num] = str;
  419.     trapmode[num] = mode;
  420.     return num;
  421. }
  422.  
  423. int deftrap(TrapFunction func)
  424. {
  425.     return deftrap2(func, 0, "");
  426. }
  427.  
  428. void align(int b)
  429. {
  430.     rt_addr = (rt_addr + (b-1)) & ~(b-1);
  431. }
  432.  
  433. static uae_u32 nullfunc(void)
  434. {
  435.     fprintf(stderr, "Null function called\n");
  436.     return 0;
  437. }
  438.  
  439. static uae_u32 getchipmemsize (void)
  440. {
  441.     return chipmem_size;
  442. }
  443.  
  444. void rtarea_init()
  445. {
  446.     uae_u32 a;
  447.     char uaever[100];
  448.     sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10);
  449.  
  450.     EXPANSION_uaeversion = ds(uaever);
  451.     EXPANSION_explibname = ds("expansion.library");
  452.     EXPANSION_doslibname = ds("dos.library");
  453.     EXPANSION_uaedevname = ds("uae.device");
  454.  
  455.     deftrap(NULL); /* Generic emulator trap */
  456.     lasttrap = 0;
  457.  
  458.     EXPANSION_nullfunc = here();
  459.     calltrap(deftrap(nullfunc));
  460.     dw(RTS);
  461.     
  462.     a = here();
  463.     /* Standard "return from 68k mode" trap */
  464.     org(0xF0FF00);
  465.     calltrap (deftrap2(m68k_mode_return, TRAPFLAG_NO_RETVAL, ""));
  466.  
  467.     org (0xF0FF80);
  468.     calltrap (deftrap (getchipmemsize));
  469.     dw (RTS);
  470.     org(a);
  471.     
  472.     filesys_install_code ();
  473. }
  474.  
  475. volatile int uae_int_requested = 0;
  476.  
  477. void set_uae_int_flag (void)
  478. {
  479.     rtarea[0xFFFB] = uae_int_requested;
  480. }
  481.  
  482. void rtarea_setup(void)
  483. {
  484. }
  485.